package game;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
/*
 * Team: Sting Arrays
 * Creators: Devin La Fleur. and Jonathan Satchell.
 * Game: Defend Chernobly
 */
public class GameFrame extends JFrame implements MouseListener{

	private JPanel contentPane;
	Dimension dim;
	Player player;
	JLabel pane, base, lblHealth;

	int Round, attack = 0, reloadCounter = 0, clip, shot = 0;

	//float pace;

	boolean roundOver;

	private JButton btnRoundOver, btnGameOver;
	
	String ammo;

	ArrayList<Enemy> enemies;
	//ArrayList<Bullet> inClip, shot = new ArrayList<Bullet>();

	/**
	 * Create the frame.
	 */
	Timer enemyTimer = new Timer(0,null);
	Timer reloadTimer = new Timer(0,null);

	public GameFrame(Player play, int numRound) {
		Round = numRound;
		player = play;
		roundOver = false;
		
		clip = player.gun.clip;
		
		ammo = clip-shot+"";
		
		//inClip = new ArrayList<Bullet>(player.gun.getClip());
		this.addMouseListener(this);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		dim = Toolkit.getDefaultToolkit ().getScreenSize();
		setBounds(new Rectangle(dim.width,(dim.height-40)));
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);

		//sets the background
		ImageIcon img = new ImageIcon("Images/Chernobyl_background.jpg");
		JLabel background = new JLabel();
		background.setBounds(0, 0, 1600, 900);
		background.setIcon(img);

		//sets the player's stats
		lblHealth = new JLabel("Health: " + player.getHealth() + " Money: " + player.money + " Round:" + Round + " Ammo:" + ammo);
		lblHealth.setText("Health: " + player.getHealth() + " Money: " + player.money + " Round:" + Round + " Ammo:" + ammo);
		lblHealth.setBounds(122, 15, 384, 14);
		contentPane.add(lblHealth);

		JButton btnPause = new JButton("Pause");
		btnPause.setBounds(10, 11, 89, 23);
		btnPause.addActionListener(new GameFrame_btnPause_actionAdapter(this));
		contentPane.add(btnPause);



		btnRoundOver = new JButton("Round Over");
		btnRoundOver.setBounds(680, 290, 365, 163);
		btnRoundOver.addActionListener(new GameFrame_btnRoundOver_actionAdapter(this));
		contentPane.add(btnRoundOver);
		btnRoundOver.setVisible(false);

		btnGameOver = new JButton("Try Again");
		btnGameOver.setBounds(680, 290, 365, 163);
		btnGameOver.addActionListener(new GameFrame_btnGameOver_actionAdapter(this));
		contentPane.add(btnGameOver);
		btnGameOver.setVisible(false);


		newRound();
		reloadClip();

		base = new JLabel();
		base.setBounds(new Rectangle(1000,300,800,600));
		img = new ImageIcon("Images/Chernobyl_With_Damon.png");
		base.setIcon(new ImageIcon(img.getImage( ).getScaledInstance(base.getWidth(),base.getHeight(), Image.SCALE_SMOOTH)));





		contentPane.add(base);

		enemyTimer = new Timer(100,enemyTimedMethod);
		reloadTimer = new Timer(player.gun.reloadTime, reloadTimedMethod);

		contentPane.add(background);


		//bulletTimer.start();
		enemyTimer.start();
	}
	
	//Used to deal solely to bullets fired
	Action reloadTimedMethod = new AbstractAction(){
		public void actionPerformed(ActionEvent e)
		{
			reloadClip();
		}
			/*
			//Checks to see if any shots are fired
			if(shot != null)
			{
				//loops through every shot fired
				for (int x = 0; x<shot.size();x++)
				{
					//moves the bullets if they are visible and shot
					if(shot.get(x).isShot() && shot.get(x).isVisible())
					{
						shot.get(x).setBounds((int)(shot.get(x).getX() - shot.get(x).getXSpeed()), (int)(shot.get(x).getY() + shot.get(x).getYSpeed()), 20, 20);

					}
					//removes if they go off screen
					if(shot.get(x).getY()>=1200 || shot.get(x).getX() <= -50)
					{
						shot.remove(x);
					}
					//checks to see if they hit anything
					else
						for(int a = 0; a < enemies.size();a++)
						{
							if(enemies.size() != 0 && shot.size() != 0 && collides(shot.get(x),enemies.get(a)))
							{
								enemies.get(a).takeDamage(player.gun.damage);
								if(enemies.get(a).getHealth() <= 0)
								{
									player.getPaid(enemies.get(a).getLoot());
									enemies.get(a).setVisible(false);
									enemies.remove(a);
									shot.get(x).setVisible(false);
									shot.remove(x);
									lblHealth.setText("Health: " + player.getHealth() + " Money: " + player.money + " Round:" + Round);
								}
								else
								{
									shot.get(x).setVisible(false);
									shot.remove(x);
								}
								break;
							}
						}
				}

			}
			//checks to see if player needs to reload
			if(inClip.size() == 0)
			{
				if(reloadCounter >= player.gun.reloadTime || reload)
				{
					reload = true;
				}
				else
					reloadCounter++;
			}
		}
		*/
	};
	
	//deals solely with enemies
	Action enemyTimedMethod = new AbstractAction(){
		public void actionPerformed(ActionEvent e)
		{
			//checks to see if any enemies are left
			if(enemies.size() != 0){
				for (int x = 0; x < enemies.size(); x++)
				{
					//checks if they are in attack range
					if(enemies.get(x).getX()>=900 && enemies.get(x).isVisible())
					{
						//checks if they can attack
						if(attack == 10)
						{
							player.changeHealth(enemies.get(x).getDamage());
							lblHealth.setText("Health: " + player.getHealth() + " Money: " + player.money + " Round:" + Round + " Ammo:" + ammo);
							attack = 0;
							if(player.getHealth() <= 0)
							{
								player.health = 0;
								int answer = JOptionPane.showConfirmDialog(null, "You died!\nYou were overrun on day " + Round + "\nwith $" + player.totalMoney +
										"\nPlay Again?", "Game Over!", JOptionPane.YES_NO_OPTION);
								if(answer == JOptionPane.YES_OPTION)
								{
									btnGameOver.setVisible(true);
									//bulletTimer.stop();
									enemyTimer.stop();
								}
								else
								{
									System.exit(1);
								}
							}
						}
						else
							attack++;

					}
					//otherwise moves them
					else if(enemies.get(x).isVisible())
					{
						enemies.get(x).setBounds(enemies.get(x).getX()+enemies.get(x).getSpeed(), enemies.get(x).getY(), enemies.get(x).getWidth(), enemies.get(x).getHeight());
					}
				}
			}
			//otherwise the round is over
			else
			{

				btnRoundOver.setVisible(true);
				//bulletTimer.stop();
				enemyTimer.stop();
			}
		}
	};
	//Collision
	public boolean collides(Component a1, Point mouse) {
        /*
		Rectangle r1 = a1.getBounds();
        Rectangle r2 = a2.getBounds();
        return r1.intersects(r2);
        */
		Rectangle rect = new Rectangle(a1.getX(),a1.getY(),a1.getWidth(),a1.getHeight());
		return rect.contains(mouse);
    }
	//Pauses the game
	public void btnPause_actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		enemyTimer.stop();
		reloadTimer.stop();
		int answer = JOptionPane.showConfirmDialog(null, "Continue?", "Game Paused", JOptionPane.YES_NO_OPTION);
		if(answer == JOptionPane.YES_OPTION)
		{
			enemyTimer.start();
			//bulletTimer.start();
		}
		else
		{

			System.exit(1);

		}


	}
	//Sets up a new round and creates number and type of enemies based on the round and randomizes their order
	public void newRound()
	{
		//Random number generator
		Random randGen = new Random();
		//int[] y = {800,750,700};
		int y = 0;
		enemies = new ArrayList<Enemy>();
		ArrayList<Enemy> temp = new ArrayList<Enemy>();
		int numEnemies = (int)(.75*Round *10);
		for(int x = 1; x <= numEnemies; x++)
		{
			if(x%3 == 0)
			{
				y = 600;
			}
			else if(x%3 == 1)
			{
				y = 550;
			}
			else
			{
				y = 700;
			}
			//randGen = new Random();
			if(x%60 == 0)
			{
				temp.add(new Enemy(Enemy.Type.TANK));
				int a = (int)-((x)*150);
				temp.get(x-1).setBounds(a, y, temp.get(x-1).getImage().getIconWidth(), temp.get(x-1).getImage().getIconHeight());
			}
			else if(x%15 == 0)
			{
				temp.add(new Enemy(Enemy.Type.SOLDIER));
				int a = (int)-((x)*75);
				temp.get(x-1).setBounds(a, y, temp.get(x-1).getImage().getIconWidth(), temp.get(x-1).getImage().getIconHeight());
			}
			else
			{
				temp.add(new Enemy(Enemy.Type.GRUNT));
				int a = (int)-((x)*100);
				temp.get(x-1).setBounds(a, y, temp.get(x-1).getImage().getIconWidth(), temp.get(x-1).getImage().getIconHeight());
				//temp.get(x-1).setBounds(0, 750, 32, 50);
			}

		}

		//Clear out the old deck of cards
		enemies.clear();
		//Loop through the ordered deck of cards until it is empty
		while(!temp.isEmpty()) {
			//Randomly pick an integer position from the ordered deck of cards
			int pos = randGen.nextInt(temp.size());
			//Remove the card at the random position and add it to the card deck
			enemies.add(temp.remove(pos));
		}
		for(int a =0; a<numEnemies; a++)
		{
			if(!enemies.get(a).equals(null))
			{

				enemies.get(a).setIcon(enemies.get(a).getImage());
				contentPane.add(enemies.get(a));
			}
			else{
				break;
			}
		}

	}
	//reloads the inClip ArrayList with bullets
	public void reloadClip()
	{
		/*
		inClip = new ArrayList<Bullet>(player.gun.getClip());
		//inClip.clear();
		for(int b = 0; b<player.gun.getClip(); b++)
		{
			inClip.add(b, new Bullet(player.gun.damage));
			inClip.get(b).setIcon(inClip.get(b).getImg());
			inClip.get(b).setBounds(1217, 384, 20, 20);

			contentPane.add(inClip.get(b));
			inClip.get(b).getParent().setComponentZOrder(inClip.get(b), 0);
		}
		*/
		shot = 0;
		reloadTimer.stop();
	}
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub

	}
	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}
	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}
	@Override
	public void mousePressed(MouseEvent e) {
	//	shoots if there are bullets otherwise waits for reload timer to reload
		// TODO Auto-generated method stub
		/*
		if(inClip.size() != 0)
		{
			inClip.get(0).shoot(e.getX(), e.getY());
			//inClip.remove(0);
			//System.out.print("Shot");
			shot.add(inClip.remove(0));
		}
		else if(reload)
		{
			reloadClip();
			//System.out.print("reloading");
			reloadCounter = 0;
			reload = false;
		}
		*/
		enemyTimer.stop();
		if(shot>=clip)
		{
			reloadTimer.start();
		}
		else
		{
			for(int x = 0; x<enemies.size(); x++)
			{
				if(enemies.get(x).getMousePosition() != null)//collides(enemies.get(x),getMousePosition()))
				{
					enemies.get(x).takeDamage(player.gun.damage);
					if(enemies.get(x).getHealth()<=0)
					{
						enemies.get(x).setVisible(false);
						player.getPaid(enemies.get(x).getLoot());
						enemies.remove(x);
					}
					break;
				}
				
			}
			shot++;
		}
		if(clip-shot==0)
		{
			ammo = "RELOAD";
		}
		else
		{
			ammo = clip-shot+"";
		}
		lblHealth.setText("Health: " + player.getHealth() + " Money: " + player.money + " Round:" + Round + " Ammo:" + ammo);
		enemyTimer.start();
	}
	@Override
	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}
	//returns player to upgrade menu after round is over
	public void btnRoundOver_actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub

		this.setVisible(false);
		Upgrade upgrade = new Upgrade(player, Round);

        // Center the window
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = upgrade.getSize();
        if (frameSize.height > screenSize.height) {
            frameSize.height = screenSize.height;
        }
        if (frameSize.width > screenSize.width) {
            frameSize.width = screenSize.width;
        }
        upgrade.setLocation((screenSize.width - frameSize.width) / 2,
                          (screenSize.height - frameSize.height) / 2);
        upgrade.setVisible(true);
	}
	public void btnGameOver_actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		this.setVisible(false);
		Upgrade upgrade = new Upgrade(new Player(), 0);

        // Center the window
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = upgrade.getSize();
        if (frameSize.height > screenSize.height) {
            frameSize.height = screenSize.height;
        }
        if (frameSize.width > screenSize.width) {
            frameSize.width = screenSize.width;
        }
        upgrade.setLocation((screenSize.width - frameSize.width) / 2,
                          (screenSize.height - frameSize.height) / 2);
        upgrade.setVisible(true);
	}
}

class GameFrame_btnPause_actionAdapter implements ActionListener {
	private GameFrame adaptee;
    GameFrame_btnPause_actionAdapter(GameFrame adaptee) {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e) {
        adaptee.btnPause_actionPerformed(e);
    }

}
class GameFrame_btnRoundOver_actionAdapter implements ActionListener {
	private GameFrame adaptee;
    GameFrame_btnRoundOver_actionAdapter(GameFrame adaptee) {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e) {
        adaptee.btnRoundOver_actionPerformed(e);
    }

}
class GameFrame_btnGameOver_actionAdapter implements ActionListener {
	private GameFrame adaptee;
    GameFrame_btnGameOver_actionAdapter(GameFrame adaptee) {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e) {
        adaptee.btnGameOver_actionPerformed(e);
    }

}